package ua.kiev.tosik.price.modules.clients.gui.files;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import org.pushingpixels.substance.api.renderers.SubstanceDefaultTableCellRenderer;
import ua.kiev.tosik.price.conf.AppConfig;
import ua.kiev.tosik.price.database.dao.IPricesFilesDao;
import ua.kiev.tosik.price.database.factory.AbstractDbFactory;
import ua.kiev.tosik.price.models.PricesFiles;
import ua.kiev.tosik.price.modules.clients.conf.ModuleConfig;
import ua.kiev.tosik.price.modules.clients.gui.prices.PricesDialog;
import ua.kiev.tosik.price.modules.clients.models.PricesFilesTableModel;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.*;
import java.io.File;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

public class PricesFilesTable {

	private JXTable table;
	private JScrollPane scrollPane;
	private PricesFilesTableModel model;
	private static Logger logger = Logger.getLogger("ua.kiev.tosik.price.modules.clients.gui.files");
	private ModuleConfig config;
	private JPopupMenu contextMenu;
	private JFileChooser fileChooser;

	protected NumberFormat numberFormat = new DecimalFormat("##,###");
	protected DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");

	public PricesFilesTable() {
		model = new PricesFilesTableModel(new ArrayList<PricesFiles>());
		config = ModuleConfig.getInstance();
		table = new JXTable(model);
		scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		table.setFillsViewportHeight(true);
		ListSelectionModel listMod = table.getSelectionModel();
		listMod.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.addHighlighter(HighlighterFactory.createSimpleStriping());
		table.setColumnControlVisible(true);
		table.packAll();

		createContextMenu();

		TableColumn firstColumn = table.getColumnModel().getColumn(0);
		firstColumn.setMinWidth(16);
		firstColumn.setMaxWidth(50);
		firstColumn.setPreferredWidth(45);
		firstColumn.setResizable(false);

		TableColumn lastColumn = table.getColumnModel().getColumn(4);
		lastColumn.setMinWidth(80);
		lastColumn.setMaxWidth(80);
		lastColumn.setPreferredWidth(80);
		lastColumn.setResizable(false);

		TableColumn sizeColumn = table.getColumnModel().getColumn(2);
		sizeColumn.setCellRenderer(new SubstanceDefaultTableCellRenderer() {
			@Override
			public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
				Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
				setHorizontalAlignment(SwingConstants.RIGHT);
				return this;
			}

			@Override
			protected void setValue(Object value) {
				Integer val = ( value != null )?(Integer)value/1024:null;
				super.setValue(numberFormat.format(val));
			}
		});

		TableColumn dateColumn = table.getColumnModel().getColumn(3);
		dateColumn.setCellRenderer(new SubstanceDefaultTableCellRenderer() {
			@Override
			public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
				Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
				setHorizontalAlignment(SwingConstants.CENTER);
				return this;
			}

			@Override
			protected void setValue(Object value) {
				super.setValue(dateFormat.format(value));
			}
		});

		table.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				int c = e.getKeyCode();
				if (c == KeyEvent.VK_DELETE) {
					int[] index = table.getSelectedRows();
					e.consume();
					deleteRowByUser(index);
				} else {
					if (c == KeyEvent.VK_ENTER) {
						e.consume();
						editRecord(table.getSelectedRow());
					}
				}
			}
		});
		table.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
					final int row = table.getSelectedRow();
					if ( row >= 0 ) {
						editRecord(table.getSelectedRow());
					}
				}
			}
			public void mouseReleased(MouseEvent e) {
				if ( e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON3 ) {
					int row = table.rowAtPoint(e.getPoint());
					// final int row = table.getSelectedRow();
					if ( row != -1 ) {
						table.setEditingRow(table.rowAtPoint(e.getPoint()));
						table.setRowSelectionInterval(row, row);
						contextMenu.show(e.getComponent(), e.getX(), e.getY());
					}
				}
			}
		});

		table.setTransferHandler(new TransferHandler() {
			@Override
			public boolean canImport(TransferSupport support) {
				return true;
			}

			@Override
			public void exportAsDrag(JComponent comp, InputEvent e, int action) {
				super.exportAsDrag(comp, e, action);
				logger.debug(comp.getClass().getSimpleName());
			}

			@Override
			@SuppressWarnings("unchecked")
			public boolean importData(TransferSupport support) {
				Transferable tr = support.getTransferable();
				DataFlavor[] flavors = tr.getTransferDataFlavors();
				for (DataFlavor flavor : flavors) {
					logger.debug("Possible flavor: " + flavor.getMimeType());
					if (flavor.isFlavorJavaFileListType() ) {
						logger.debug("Catch dropped file");
						java.util.List<File> o;
						try {
							o = (java.util.List<File>)tr.getTransferData(flavor);
							for ( File f : o ) {
								logger.debug("Catch : " + f.getAbsolutePath());
								PricesDialog.getInstance().openFileUploadDialog(f);
							}
							logger.debug(o.getClass());
						} catch (Exception e) {
							logger.warn(e.getMessage(), e);
						}
					}
				}
				return true;
			}
		});

	}

	private void createContextMenu() {
		contextMenu = new JPopupMenu();
		JMenuItem exportFile = new JMenuItem(config.get("clients.files.table.tab.context.export.text"), new ImageIcon(config.get("clients.files.table.tab.context.export.icon")));
		JMenuItem deleteFile = new JMenuItem(config.get("clients.files.table.tab.context.delete.text"), new ImageIcon(config.get("clients.files.table.tab.context.delete.icon")));
		JMenuItem clearPrices = new JMenuItem(config.get("clients.files.table.tab.context.clear.text"), new ImageIcon(config.get("clients.files.table.tab.context.clear.icon")));
		contextMenu.add(exportFile);
		contextMenu.add(deleteFile);
		contextMenu.add(clearPrices);

		exportFile.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int row = table.getSelectedRow();
				try {
					saveFileAsDialog(getModel().getRow(row));
				} catch (Exception e1) {
					logger.error(e1);
					JXErrorPane.showDialog(e1);
				}
			}
		});
		deleteFile.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int[] row = table.getSelectedRows();
				deleteRowByUser(row);
			}
		});
		clearPrices.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int row = table.getSelectedRow();
				if ( row >= 0 ) {
					clearPrices(getModel().getRow(row), row);
				}
			}
		});

	}

	private void clearPrices(PricesFiles pricesFiles, int rowIndex) {
		int res = JOptionPane.NO_OPTION;
		try {
			res = JOptionPane.showConfirmDialog(table, config.get("clients.files.table.clearPrices.message"), config.get("clients.files.table.clearPrices.message"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, new ImageIcon(config.get("clients.files.table.deleteRow.icon")));
		} catch (Exception e) {
			logger.warn(e.getLocalizedMessage());
		}
		if (res == JOptionPane.YES_OPTION) {
			PricesDialog.getInstance().clearPrices(pricesFiles, rowIndex);
		}
	}

	public void saveFileAsDialog(PricesFiles pricesFiles) throws Exception {
		if ( pricesFiles == null ) {
			return;
		}
		if ( fileChooser == null ) {
			fileChooser = new JFileChooser();
			FileFilter filter = new FileNameExtensionFilter("Excel файл (*.xls)", "xls");
			fileChooser.addChoosableFileFilter(filter);
		}
		fileChooser.setMultiSelectionEnabled(false);
		if ( !AppConfig.getInstance().get("app.lastDir").equals("") ) {
			fileChooser.setCurrentDirectory(new File(AppConfig.getInstance().get("app.lastDir")));
		}
		File newFile = new File(pricesFiles.getFileName());
		fileChooser.setSelectedFile(newFile);
		fileChooser.setDialogTitle(config.get("clients.editor.prices.saveAs.fileChooser.title"));
		int returnVal = fileChooser.showSaveDialog(table);
		if ( returnVal == JFileChooser.APPROVE_OPTION ) {
			newFile = fileChooser.getSelectedFile();
			if ( newFile != null ) {
				logger.debug("File: " + newFile.getAbsolutePath());
				if ( newFile.exists() ) {
					int op = JOptionPane.showConfirmDialog(table, config.get("clients.editor.prices.saveAs.fileChooser.overwrite"), config.get("clients.editor.prices.saveAs.fileChooser.overwrite"), JOptionPane.YES_NO_OPTION);
					if ( op != JFileChooser.APPROVE_OPTION ) {
						saveFileAsDialog(pricesFiles);
					} else {
						saveFile(pricesFiles, newFile);
					}
				} else {
					saveFile(pricesFiles, newFile);
				}
			}
		}
	}

	private void saveFile(PricesFiles pricesFiles, File file) throws Exception {
		if ( file.isDirectory() ) {
			logger.debug("Can't create file: " + file.getAbsolutePath());
			throw new Exception("Can't create file: " + file.getAbsolutePath());
		}
		logger.debug("Saving file: " + pricesFiles.getFileName() + " to " + file.getAbsolutePath());
		byte[] fileContent = null;
		if ( pricesFiles.getSourceFile() != null && pricesFiles.getSourceFile().length > 0 ) {
			fileContent = pricesFiles.getSourceFile();
		} else {
			IPricesFilesDao pricesFilesDao = AbstractDbFactory.getInstance(AppConfig.getInstance().get("app.dbtype")).createPricesFilesDao();
			fileContent = pricesFilesDao.loadFile(pricesFiles.getId());
		}
		if ( fileContent != null && fileContent.length > 0 ) {
			FileUtils.writeByteArrayToFile(file, fileContent);
		}
	}


	private void editRecord(int selectedRow) {
		PricesDialog.getInstance().createRawPreview(selectedRow);
	}

	private void deleteRowByUser(int[] index) {
		int res = JOptionPane.NO_OPTION;
		int idx = table.convertRowIndexToModel(index[0]);
		try {
			res = JOptionPane.showConfirmDialog(table, config.get("clients.files.table.deleteRow.message"), config.get("clients.files.table.deleteRow.text"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, new ImageIcon(config.get("clients.files.table.deleteRow.icon")));
		} catch (Exception e) {
			logger.warn(e.getLocalizedMessage());
		}
		if (res == JOptionPane.YES_OPTION) {
			PricesFiles pricesFiles = getModel().getRow(idx);
			PricesDialog.getInstance().deletePricesFiles(pricesFiles, idx);
			/*
			for (int i=index.length - 1; i >= 0; --i){
				model.removeRow(index[i]);
			} */
		}
	}

	public JScrollPane getTable() {
		return scrollPane;
	}

	public PricesFilesTableModel getModel() {
		return model;
	}



}
